package cn.walls1717.wallsmall.search.thread;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

/**
 * 使用线程池
 * 
 * 直接new线程在高并发下容易导致资源耗尽，使用线程池可以复用资源
 *
 * @author walls1717
 * @since 2022/11/08 20:10
 **/
@Slf4j
public class ThreadTest4 {
    /**
     * 线程池应该保证公用，不能每来一个线程就new一个线程池
     * <p>
     * 固定数量的线程池，10个线程
     */
    public static final ExecutorService service = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        service.execute(() -> {
            log.info("当前线程id -> {}", Thread.currentThread().getId());
            int i = 10 / 2;
            log.info("运行结果 -> {}", i);
        });

        /*
         线程池七大参数：
         1.corePoolSize：核心线程数。线程池创建好后就准备就绪的线程数量，核心线程不会销毁，除非指定allowCoreThreadTimeOut
         2.maximumPoolSize：最大线程数。控制资源。
         3.keepAliveTime：空闲线程之外的线程的存活时间。
           也就是(maximumPoolSize - corePoolSize)的线程的存活时间，超过该时间线程就会销毁。
         4.unit：空闲线程存活时间的时间单位。
         5.BlockingQueue<Runnable> workQueue：阻塞队列。没有抢到线程的任务会被放到阻塞队列。
           只要线程池线程空闲，就会从此队列取出任务执行。
           new LinkedBlockingDeque<>()默认是Integer的最大值，可能导致内存不足。
         6.threadFactory：线程的创建工厂。
         7.handler：处理阻塞队列与最大空闲线程都满的情况。按照指定的拒绝策略拒绝执行任务。

         执行顺序：
         1.线程池创建，准备好core数量的核心线程，准备接收任务。
         2.core满了，会将再来的任务放入阻塞队列，空闲的core去阻塞队列取出任务执行。
         3.阻塞队列也满了，会创建新线程执行，数量不会超过指定的max。
         4.max线程也满了，会按照handler指定的拒绝策略拒绝任务。
         5.max都执行完成，除了core线程不会销毁，其余的空闲线程会在执行的keepAliveTime后销毁。

         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy()
        );

        // Executors.newCachedThreadPool();
        // Executors.newFixedThreadPool(10);
        // Executors.newScheduledThreadPool();
        // Executors.newSingleThreadExecutor();

    }
}
